<?php
// +----------------------------------------------------------------------
// | Description: 货币余额 - CurrencyBalance
// +----------------------------------------------------------------------
// | Author: liaoyizhi <liaoyizhi@gmail.com>
// +----------------------------------------------------------------------

namespace codelord\finance\model;

use think\Exception;
use think\Model;

class CurrencyBalance extends Model {
    /**
     * 获取用户货币信息（余额等）
     * @param int  $uid   用户的id主键号'
     * @param bool $field 是否屏蔽敏感信息
     * @return array|null
     */
    public function getUserBalance(int $uid, bool $field = false) : ? array
    {
        //外部接口不返回敏感信息
        if ($field) {
            $currency = $this->alias('a')
                ->field('a.amount,a.amount_lock,a.currency_id, b.name, b.code')
                ->join('__CURRENCY__ b', 'a.currency_id = b.id')
                ->where(['a.UID' => $uid])
                ->select();
        } else {
            $currency = $this->alias('a')
                ->field('a.*, b.name, b.code')
                ->join('__CURRENCY__ b', 'a.currency_id = b.id')
                ->where(['a.uid' => $uid])
                ->select();
        }

        // 未产生任何余额，返回空数组
        if (!$currency) {
            return $currency;
        }
        // 重新组合数组，以currency_id为键名
        $currency_fix = [];

        foreach ($currency as $val) {
            $currency_fix[$val['currency_id']] = $val;
        }

        return $currency_fix;
    }

    /**
     * 检测用户资金是否足够进行某操作
     * @param array $currency 组装的消费数组
     * @param array $all_math 相关的消费算法数组
     * @return void
     */
    public function checkCurrencyIsEnough(array $currency,array $all_math) : void
    {
        $uid = $currency['uid'];

        $user_currency = $this->getUserBalance($uid);

        //逐一检测
        foreach ($currency['currency'] as $key => $data) {
            $math = $all_math[$key];
            $math_rule = explode(',', $math['math']);
            // 只检测需要扣除的货币是否足够
            if (($math_rule[0] < 0 && $type = '可用') || ($math_rule[1] < 0 && $type = '冻结')) {
                if (!isset($user_currency[$data[0]])) {
                    throw new Exception($type . '余额不足', 20006);
                }
                $balance = $user_currency[$data[0]];
                if ($math_rule[0] < 0 && $balance['amount'] < $data[1] || $math_rule[1] < 0 && $balance['amount_lock'] < $data[2]) {
                    throw new Exception($balance['name'] . $type . '余额不足', 20006);
                }
            }
        }
    }

    /**
     * 更新用户的货币余额
     * @param array $currency_data 数组
     * @return void
     */
    public function updateCurrencyBalance(array $currency_data) : void
    {
        $uid = $currency_data['uid'];
        $status = true;
        foreach ($currency_data['currency'] as $currency) {
            // 检测当前类型货币是否已存在余额
            $balance_id = $this->where(['uid' => $uid, 'currency_id' => $currency[0]])->value('id');
            // 不存在则插入
            if (!$balance_id) {
                $data = [
                    'uid' => $uid,
                    'amount' => $currency[1],
                    'amount_lock' => $currency[2],
                    'currency_id' => $currency[0]
                ];
                $status = $status && $this->insert($data);
            } else {
                $amount = true;
                $lock = true;
                // 存在则更新
                if ($currency[1] !== 0){
                    $amount = $this->where('id',$balance_id)->setInc('amount',$currency[1]);
                }
                if ($currency[2] !== 0){
                    $lock = $this->where('id',$balance_id)->setInc('amount_lock',$currency[2]);
                }

                $status = $status && $amount && $lock;
            }
        }

        if ($status === false) {
            throw new Exception('用户货币余额更新失败', 20007);
        }
    }
}
